from django.db import models
from utils.models import CoreModel
from utils.models import CommonStatus
from product.models import Product
from system.models import User


class WarehouseStatus(models.TextChoices):
    """仓库状态枚举类"""
    ACTIVE = 'active', '激活'
    INACTIVE = 'inactive', '非激活'
    CLOSED = 'closed', '已关闭'


class LocationStatus(models.TextChoices):
    """库位状态枚举类"""
    AVAILABLE = 'available', '可用'
    UNAVAILABLE = 'unavailable', '不可用'
    LOCKED = 'locked', '已锁定'


class TransactionType(models.TextChoices):
    """库存交易类型枚举类"""
    INBOUND = 'inbound', '入库'
    OUTBOUND = 'outbound', '出库'
    TRANSFER = 'transfer', '移库'
    ADJUSTMENT = 'adjustment', '调整'
    CHECK = 'check', '盘点'


class InventoryCheckStatus(models.TextChoices):
    """库存盘点状态枚举类"""
    CREATED = 'created', '已创建'
    IN_PROGRESS = 'in_progress', '进行中'
    COMPLETED = 'completed', '已完成'
    CANCELLED = 'cancelled', '已取消'


class Warehouse(CoreModel):
    """仓库模型

    存储仓库的基本信息，包括名称、地址、负责人等
    """
    warehouse_id = models.AutoField(primary_key=True, verbose_name="仓库ID", help_text="仓库的唯一标识")
    warehouse_code = models.CharField(max_length=50, unique=True, verbose_name="仓库编码", help_text="仓库的唯一编码")
    warehouse_name = models.CharField(max_length=100, verbose_name="仓库名称", help_text="仓库的名称")
    description = models.TextField(blank=True, null=True, verbose_name="仓库描述", help_text="仓库的详细描述")
    address = models.CharField(max_length=255, blank=True, null=True, verbose_name="仓库地址", help_text="仓库的详细地址")
    contact_person = models.CharField(max_length=50, blank=True, null=True, verbose_name="联系人", help_text="仓库联系人")
    contact_phone = models.CharField(max_length=20, blank=True, null=True, verbose_name="联系电话", help_text="仓库联系电话")
    manager_id = models.IntegerField(blank=True, null=True, verbose_name="仓库管理员ID", help_text="负责仓库管理的用户ID")
    status = models.CharField(
        max_length=20,
        choices=WarehouseStatus.choices,
        default=WarehouseStatus.ACTIVE,
        verbose_name="仓库状态",
        help_text="仓库的当前状态"
    )
    is_primary = models.BooleanField(default=False, verbose_name="是否主仓库", help_text="是否为企业主仓库")
    capacity = models.IntegerField(blank=True, null=True, verbose_name="仓库容量", help_text="仓库的最大容量")
    area = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, verbose_name="仓库面积", help_text="仓库的占地面积，单位：平方米")

    class Meta:
        verbose_name = "仓库"
        verbose_name_plural = verbose_name
        ordering = ['warehouse_code']
        db_table = 'inventory_warehouse'
        indexes = [models.Index(fields=['warehouse_code'])]

    def __str__(self):
        return f"{self.warehouse_name}({self.warehouse_code})"


class Location(CoreModel):
    """库位模型

    存储库位的详细信息，包括位置编码、类型、状态等
    """
    location_id = models.AutoField(primary_key=True, verbose_name="库位ID", help_text="库位的唯一标识")
    warehouse = models.ForeignKey(
        Warehouse,
        on_delete=models.CASCADE,
        related_name='locations',
        verbose_name="所属仓库",
        help_text="库位所属的仓库",
        null=True,
        blank=True
    )
    location_code = models.CharField(max_length=50, verbose_name="库位编码", help_text="库位的唯一编码")
    location_name = models.CharField(max_length=100, blank=True, null=True, verbose_name="库位名称", help_text="库位的名称")
    location_type = models.CharField(max_length=50, blank=True, null=True, verbose_name="库位类型", help_text="库位的类型，如：货架、托盘区、阴凉区等")
    description = models.TextField(blank=True, null=True, verbose_name="库位描述", help_text="库位的详细描述")
    status = models.CharField(
        max_length=20,
        choices=LocationStatus.choices,
        default=LocationStatus.AVAILABLE,
        verbose_name="库位状态",
        help_text="库位的当前状态"
    )
    capacity = models.IntegerField(blank=True, null=True, verbose_name="库位容量", help_text="库位的最大容量")
    current_load = models.IntegerField(default=0, verbose_name="当前负载", help_text="库位当前存放的物品数量")
    is_aisle = models.BooleanField(default=False, verbose_name="是否为通道", help_text="该库位是否为仓库通道")
    zone = models.CharField(max_length=50, blank=True, null=True, verbose_name="库区", help_text="库位所属的库区")
    row = models.CharField(max_length=10, blank=True, null=True, verbose_name="排", help_text="库位的排号")
    column = models.CharField(max_length=10, blank=True, null=True, verbose_name="列", help_text="库位的列号")
    level = models.CharField(max_length=10, blank=True, null=True, verbose_name="层", help_text="库位的层号")

    class Meta:
        verbose_name = "库位"
        verbose_name_plural = verbose_name
        ordering = ['warehouse', 'location_code']
        db_table = 'inventory_location'
        unique_together = ['warehouse', 'location_code']  # 每个仓库内库位编码唯一
        indexes = [models.Index(fields=['warehouse', 'location_code'])]

    def __str__(self):
        return f"{self.warehouse.warehouse_name} - {self.location_code}"


class Inventory(CoreModel):
    """库存模型

    存储当前库存数量，与产品和库位关联
    """
    inventory_id = models.AutoField(primary_key=True, verbose_name="库存ID", help_text="库存记录的唯一标识")
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE,
        related_name='inventories',
        verbose_name="产品",
        help_text="库存对应的产品"
    )
    warehouse = models.ForeignKey(
        Warehouse,
        on_delete=models.CASCADE,
        related_name='inventories',
        verbose_name="仓库",
        help_text="库存所在的仓库"
    )
    location = models.ForeignKey(
        Location,
        on_delete=models.CASCADE,
        related_name='inventories',
        verbose_name="库位",
        help_text="库存所在的库位"
    )
    quantity = models.DecimalField(max_digits=14, decimal_places=4, default=0, verbose_name="库存数量", help_text="当前库存数量")
    available_quantity = models.DecimalField(max_digits=14, decimal_places=4, default=0, verbose_name="可用数量", help_text="当前可用库存数量")
    reserved_quantity = models.DecimalField(max_digits=14, decimal_places=4, default=0, verbose_name="预留数量", help_text="已预留但未出库的数量")
    unit_cost = models.DecimalField(max_digits=14, decimal_places=4, blank=True, null=True, verbose_name="单位成本", help_text="产品的单位成本")
    lot_number = models.CharField(max_length=50, blank=True, null=True, verbose_name="批次号", help_text="产品的批次号")
    serial_number = models.CharField(max_length=100, blank=True, null=True, verbose_name="序列号", help_text="产品的序列号")
    expiry_date = models.DateField(blank=True, null=True, verbose_name="过期日期", help_text="产品的过期日期")
    manufactured_date = models.DateField(blank=True, null=True, verbose_name="生产日期", help_text="产品的生产日期")

    class Meta:
        verbose_name = "库存"
        verbose_name_plural = verbose_name
        ordering = ['product', 'warehouse', 'location']
        db_table = 'inventory_inventory'
        indexes = [
            models.Index(fields=['product', 'warehouse', 'location']),
            models.Index(fields=['lot_number']),
            models.Index(fields=['serial_number']),
            models.Index(fields=['expiry_date'])
        ]

    def __str__(self):
        return f"{self.product.name} - {self.warehouse.warehouse_name} - {self.location.location_code}"


class InventoryTransaction(CoreModel):
    """库存交易记录模型

    记录所有库存变动的交易记录，包括入库、出库、移库、调整等
    """
    transaction_id = models.AutoField(primary_key=True, verbose_name="交易ID", help_text="交易记录的唯一标识")
    transaction_type = models.CharField(
        max_length=20,
        choices=TransactionType.choices,
        verbose_name="交易类型",
        help_text="库存交易的类型"
    )
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE,
        related_name='transactions',
        verbose_name="产品",
        help_text="交易涉及的产品"
    )
    from_warehouse = models.ForeignKey(
        Warehouse,
        on_delete=models.CASCADE,
        related_name='outgoing_transactions',
        blank=True,
        null=True,
        verbose_name="源仓库",
        help_text="交易的源仓库（适用于出库和移库）"
    )
    to_warehouse = models.ForeignKey(
        Warehouse,
        on_delete=models.CASCADE,
        related_name='incoming_transactions',
        blank=True,
        null=True,
        verbose_name="目标仓库",
        help_text="交易的目标仓库（适用于入库和移库）"
    )
    from_location = models.ForeignKey(
        Location,
        on_delete=models.CASCADE,
        related_name='outgoing_transactions',
        blank=True,
        null=True,
        verbose_name="源库位",
        help_text="交易的源库位（适用于出库和移库）"
    )
    to_location = models.ForeignKey(
        Location,
        on_delete=models.CASCADE,
        related_name='incoming_transactions',
        blank=True,
        null=True,
        verbose_name="目标库位",
        help_text="交易的目标库位（适用于入库和移库）"
    )
    quantity = models.DecimalField(max_digits=14, decimal_places=4, verbose_name="交易数量", help_text="交易的产品数量")
    unit_cost = models.DecimalField(max_digits=14, decimal_places=4, blank=True, null=True, verbose_name="交易单位成本", help_text="交易时的单位成本")
    total_cost = models.DecimalField(max_digits=14, decimal_places=4, blank=True, null=True, verbose_name="交易总成本", help_text="交易的总成本")
    reference_document = models.CharField(max_length=100, blank=True, null=True, verbose_name="参考单据", help_text="关联的业务单据号")
    reference_type = models.CharField(max_length=50, blank=True, null=True, verbose_name="参考类型", help_text="关联的业务单据类型")
    remark = models.TextField(blank=True, null=True, verbose_name="交易备注", help_text="交易的备注信息")
    lot_number = models.CharField(max_length=50, blank=True, null=True, verbose_name="批次号", help_text="交易产品的批次号")
    serial_number = models.CharField(max_length=100, blank=True, null=True, verbose_name="序列号", help_text="交易产品的序列号")

    class Meta:
        verbose_name = "库存交易记录"
        verbose_name_plural = verbose_name
        ordering = ['-create_time']
        db_table = 'inventory_transaction'
        indexes = [
            models.Index(fields=['product', 'transaction_type']),
            models.Index(fields=['reference_document']),
            models.Index(fields=['create_time'])
        ]

    def __str__(self):
        return f"{self.transaction_type} - {self.product.name} - {self.quantity}"


class InventoryCheck(CoreModel):
    """库存盘点模型

    记录库存盘点信息，包括盘点单号、状态、负责人等
    """
    check_id = models.AutoField(primary_key=True, verbose_name="盘点ID", help_text="盘点记录的唯一标识")
    check_code = models.CharField(max_length=50, unique=True, verbose_name="盘点单号", help_text="盘点单的唯一编号")
    warehouse = models.ForeignKey(
        Warehouse,
        on_delete=models.CASCADE,
        related_name='checks',
        verbose_name="盘点仓库",
        help_text="进行盘点的仓库"
    )
    status = models.CharField(
        max_length=20,
        choices=InventoryCheckStatus.choices,
        default=InventoryCheckStatus.CREATED,
        verbose_name="盘点状态",
        help_text="盘点的当前状态"
    )
    check_date = models.DateField(verbose_name="盘点日期", help_text="进行盘点的日期")
    checker_id = models.IntegerField(verbose_name="盘点人ID", help_text="负责盘点的人员ID")
    approver_id = models.IntegerField(blank=True, null=True, verbose_name="审批人ID", help_text="审批盘点结果的人员ID")
    approval_date = models.DateTimeField(blank=True, null=True, verbose_name="审批日期", help_text="审批盘点结果的日期和时间")
    start_time = models.DateTimeField(blank=True, null=True, verbose_name="开始时间", help_text="盘点开始的时间")
    end_time = models.DateTimeField(blank=True, null=True, verbose_name="结束时间", help_text="盘点结束的时间")
    total_variance_quantity = models.DecimalField(max_digits=14, decimal_places=4, default=0, verbose_name="总数量差异", help_text="盘点的总数量差异")
    total_variance_amount = models.DecimalField(max_digits=14, decimal_places=4, default=0, verbose_name="总金额差异", help_text="盘点的总金额差异")
    remark = models.TextField(blank=True, null=True, verbose_name="盘点备注", help_text="盘点的备注信息")

    class Meta:
        verbose_name = "库存盘点"
        verbose_name_plural = verbose_name
        ordering = ['-check_date']
        db_table = 'inventory_check'
        indexes = [models.Index(fields=['check_code'])]

    def __str__(self):
        return self.check_code


class InventoryCheckDetail(CoreModel):
    """库存盘点明细模型

    记录每次盘点的具体产品和数量差异
    """
    detail_id = models.AutoField(primary_key=True, verbose_name="盘点明细ID", help_text="盘点明细的唯一标识")
    inventory_check = models.ForeignKey(
        InventoryCheck,
        on_delete=models.CASCADE,
        related_name='details',
        verbose_name="盘点单",
        help_text="所属的盘点单"
    )
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE,
        related_name='check_details',
        verbose_name="产品",
        help_text="盘点的产品"
    )
    location = models.ForeignKey(
        Location,
        on_delete=models.CASCADE,
        related_name='check_details',
        verbose_name="库位",
        help_text="产品所在的库位"
    )
    system_quantity = models.DecimalField(max_digits=14, decimal_places=4, verbose_name="系统数量", help_text="系统记录的库存数量")
    actual_quantity = models.DecimalField(max_digits=14, decimal_places=4, verbose_name="实际数量", help_text="盘点实际数量")
    variance_quantity = models.DecimalField(max_digits=14, decimal_places=4, verbose_name="数量差异", help_text="实际数量与系统数量的差异")
    unit_cost = models.DecimalField(max_digits=14, decimal_places=4, blank=True, null=True, verbose_name="单位成本", help_text="产品的单位成本")
    variance_amount = models.DecimalField(max_digits=14, decimal_places=4, verbose_name="金额差异", help_text="差异数量乘以单位成本的金额差异")
    remark = models.TextField(blank=True, null=True, verbose_name="明细备注", help_text="盘点明细的备注信息")
    lot_number = models.CharField(max_length=50, blank=True, null=True, verbose_name="批次号", help_text="产品的批次号")
    serial_number = models.CharField(max_length=100, blank=True, null=True, verbose_name="序列号", help_text="产品的序列号")

    class Meta:
        verbose_name = "库存盘点明细"
        verbose_name_plural = verbose_name
        ordering = ['inventory_check', 'product']
        db_table = 'inventory_check_detail'
        indexes = [models.Index(fields=['inventory_check', 'product', 'location'])]

    def __str__(self):
        return f"{self.inventory_check.check_code} - {self.product.name}"